"""JSON处理相关节点"""

import json
import datetime
import os
from pocketflow import Node

class SaveJSONNode(Node):
    """统一的JSON文件保存节点"""
    
    def prep(self, shared):
        return {
            "final_output": shared["final_output"],
            "output_path": shared.get("output_path", "output.json")
        }
    
    def exec(self, context):
        """验证JSON格式并准备保存"""
        final_output = context["final_output"]
        
        # 处理不同格式的JSON数据
        try:
            if not isinstance(final_output, dict):
                raise ValueError(f"final_output必须是字典对象，实际为: {type(final_output)}")
            json_data = final_output
            
            # 重新格式化确保一致性
            return json.dumps(json_data, ensure_ascii=False, indent=2)
        except Exception as e:
            raise ValueError(f"JSON格式验证失败: {str(e)}")
    
    def post(self, shared, prep_res, exec_res):
        """保存JSON文件到磁盘并显示统计信息"""
        output_path = prep_res["output_path"]
        
        try:
            # 写入文件
            with open(output_path, 'w', encoding='utf-8') as f:
                f.write(exec_res)
            
            # 解析JSON以获取统计信息
            result_data = json.loads(exec_res)
            print(f"\n✅ JSON文件已保存到 '{output_path}'")
            print(f"📊 统计信息:")
            print(f"   - 证明材料清单数: {len(result_data.get('items', []))}")
            
            # 显示模块分布统计
            modules = {}
            for item in result_data.get('items', []):
                module = item.get('module', '未知模块')
                modules[module] = modules.get(module, 0) + 1
            
            for module, count in sorted(modules.items()):
                print(f"   - {module}: {count} 项")
            
            # 检查是否启用交互式修改
            if shared.get("enable_interactive", False):
                return "interactive"
            else:
                return "complete"
                
        except Exception as e:
            print(f"❌ 保存文件失败: {e}")
            return "error"

class ExportJSONNode(Node):
    """JSON数据格式化节点，仅负责数据转换"""
    
    def prep(self, shared):
        return {
            "materials": shared["materials"], 
            "source_file": shared.get("pdf_path", "未知文件")
        }

    def exec(self, context):
        """将materials转换为符合Schema的JSON格式"""
        materials = context["materials"]
        source_file = context["source_file"]
        
        # 按module属性对materials数组进行排序
        sorted_materials = sorted(materials, key=lambda x: x.get("module", ""))
        
        # 创建符合Schema的JSON结构
        result = {
            "metadata": {
                "source_file": source_file,
                "generated_at": datetime.datetime.now().isoformat(),
                "version": "1.0"
            },
            "items": sorted_materials
        }
        
        return result

    def post(self, shared, prep_res, exec_res):
        """存储JSON数据到shared，显示处理完成信息"""
        # 存储JSON数据（对象格式，便于后续处理）
        shared["final_output"] = exec_res
        
        # 显示数据处理完成信息（不涉及文件操作）
        print(f"\n🔄 JSON数据格式化完成")
        print(f"📊 处理统计:")
        print(f"   - 生成证明材料清单: {len(exec_res.get('items', []))} 项")
        
        # 显示模块分布
        modules = {}
        for item in exec_res.get('items', []):
            module = item.get('module', '未知模块')
            modules[module] = modules.get(module, 0) + 1
        
        for module, count in sorted(modules.items()):
            print(f"   - {module}: {count} 项")
        
        # 根据交互式设置决定下一步
        if shared.get("enable_interactive", False):
            return "save_and_interactive"
        else:
            return "save_and_complete"

class LoadExistingJSONNode(Node):
    """加载现有JSON文件的节点，用于快速交互模式"""
    
    def prep(self, shared):
        return shared.get("output_path", "output.json")
    
    def exec(self, output_path):
        """加载并解析现有的JSON文件"""
        try:
            # 检查文件是否存在
            if not os.path.exists(output_path):
                raise FileNotFoundError(f"JSON文件不存在: {output_path}")
            
            # 读取并解析JSON文件
            with open(output_path, 'r', encoding='utf-8') as f:
                content = f.read()
                json_data = json.loads(content)
            
            print(f"📄 加载现有JSON文件: {output_path}")
            
            # 显示文件基本信息
            if "metadata" in json_data:
                metadata = json_data["metadata"]
                print(f"📊 文件信息:")
                if "source_file" in metadata:
                    print(f"   - 源文件: {metadata['source_file']}")
                if "generated_at" in metadata:
                    print(f"   - 生成时间: {metadata['generated_at']}")
                if "interactive_modified" in metadata:
                    modified = metadata.get("interactive_modified", False)
                    print(f"   - 已有修改: {'是' if modified else '否'}")
                if "modification_count" in metadata:
                    count = metadata.get("modification_count", 0)
                    if count > 0:
                        print(f"   - 修改次数: {count}")
            
            # 显示条目统计
            if "items" in json_data:
                item_count = len(json_data["items"])
                print(f"✅ JSON文件验证通过! 包含 {item_count} 个证明材料清单")
                
                # 统计模块分布
                modules = {}
                for item in json_data["items"]:
                    module = item.get("module", "未知模块")
                    modules[module] = modules.get(module, 0) + 1
                
                if modules:
                    print(f"📈 模块分布: {dict(sorted(modules.items()))}")
            
            return json_data
            
        except FileNotFoundError as e:
            raise Exception(f"文件加载失败: {e}")
        except json.JSONDecodeError as e:
            raise Exception(f"JSON格式错误: {e}")
        except Exception as e:
            raise Exception(f"加载JSON文件时出错: {e}")
    
    def post(self, shared, prep_res, exec_res):
        """将加载的数据存入shared存储"""
        # 存储加载的JSON数据
        shared["final_output"] = exec_res
        
        # 初始化交互式修改相关数据
        shared["modification_log"] = []
        shared["enable_interactive"] = True
        
        return "validate"

class ValidateJSONNode(Node):
    """验证JSON文件格式和Schema一致性的节点"""
    
    def prep(self, shared):
        return shared["final_output"]
    
    def exec(self, json_data):
        """验证JSON格式和必需字段"""
        try:
            # 验证基本结构
            if not isinstance(json_data, dict):
                raise ValueError("JSON数据必须是一个对象")
            
            # 验证必需的顶级字段
            required_fields = ["metadata", "items"]
            for field in required_fields:
                if field not in json_data:
                    raise ValueError(f"缺少必需字段: {field}")
            
            # 验证metadata字段
            metadata = json_data["metadata"]
            if not isinstance(metadata, dict):
                raise ValueError("metadata必须是一个对象")
            
            # 验证items字段
            items = json_data["items"]
            if not isinstance(items, list):
                raise ValueError("items必须是一个数组")
            
            # 验证每个item的必需字段
            required_item_fields = ["id", "module", "category", "checkpoint", "materials"]
            for i, item in enumerate(items):
                if not isinstance(item, dict):
                    raise ValueError(f"第{i+1}个item必须是一个对象")
                
                for field in required_item_fields:
                    if field not in item:
                        raise ValueError(f"第{i+1}个item缺少必需字段: {field}")
                
                # 验证materials字段
                if not isinstance(item["materials"], list):
                    raise ValueError(f"第{i+1}个item的materials必须是一个数组")
            
            return {"valid": True, "message": "JSON验证通过"}
            
        except Exception as e:
            return {"valid": False, "message": str(e)}
    
    def post(self, shared, prep_res, exec_res):
        """根据验证结果决定下一步流程"""
        if exec_res["valid"]:
            print("✅ JSON格式验证通过!")
            return "direct_interactive"
        else:
            print(f"❌ JSON验证失败: {exec_res['message']}")
            return "invalid"

class FinalizeJSONNode(Node):
    """JSON元数据更新和数据清理节点，不涉及文件操作"""
    
    def prep(self, shared):
        return {
            "final_output": shared["final_output"],
            "modification_log": shared.get("modification_log", [])
        }
    
    def exec(self, context):
        """更新元数据并验证JSON格式完整性"""
        try:
            # 处理JSON数据（统一为对象）
            final_output = context["final_output"]
            if not isinstance(final_output, dict):
                raise ValueError("final_output必须是字典对象")
            current_data = final_output.copy()
            
            modification_log = context["modification_log"]
            
            # 更新交互式修改相关的元数据
            if modification_log:
                current_data["metadata"]["interactive_modified"] = True
                current_data["metadata"]["modification_count"] = len(modification_log)
                current_data["metadata"]["last_modified_at"] = datetime.datetime.now().isoformat()
            else:
                current_data["metadata"]["interactive_modified"] = False
                current_data["metadata"]["modification_count"] = 0
            
            # 验证JSON格式完整性
            self._validate_json_schema(current_data)
            
            return current_data
            
        except Exception as e:
            raise ValueError(f"最终化JSON时出错: {str(e)}")
    
    def post(self, shared, prep_res, exec_res):
        """更新shared数据并清理临时数据"""
        # 更新最终输出数据
        shared["final_output"] = exec_res
        
        # 显示最终化完成信息
        modification_count = exec_res.get("metadata", {}).get("modification_count", 0)
        print(f"\n🔄 JSON数据最终化完成")
        if modification_count > 0:
            print(f"📊 本次会话共进行了 {modification_count} 次修改")
        else:
            print("📊 本次会话未进行任何修改")
        
        # 清理临时数据
        if "modification_log" in shared:
            del shared["modification_log"]
        
        print("✨ 准备保存最终JSON文件...")
        return "save"
    
    def _validate_json_schema(self, data: dict):
        """验证JSON Schema一致性"""
        required_fields = ["metadata", "items"]
        for field in required_fields:
            if field not in data:
                raise ValueError(f"缺少必需字段: {field}")
        
        # 验证每个item的必需字段
        for i, item in enumerate(data.get("items", [])):
            item_required = ["id", "module", "category", "checkpoint", "materials"]
            for field in item_required:
                if field not in item:
                    raise ValueError(f"项目 {i} 缺少必需字段: {field}")
